#include "Network.h"

void TcpClient::onRecv(const toolkit::Buffer::Ptr &buf) {
    if (_data_callback) {
        _data_callback(buf);
    }
}

void TcpClient::onError(const toolkit::SockException &err) {
    if (err.getErrCode() != toolkit::Err_shutdown) {
        if (_auto_reconnect) {
            std::weak_ptr<TcpClient> self = std::dynamic_pointer_cast<TcpClient>(shared_from_this());
            _timer.reset(new toolkit::Timer(
                _reconnect_time,
                [self]() {
                    auto strong_self = self.lock();
                    SPDLOG_INFO("reconnecting to {}:{}", strong_self->_ip, strong_self->_port);
                    if (strong_self)
                        strong_self->Connect();
                    return false;
                },
                nullptr));
        }
    }
}

void TcpClient::onConnect(const toolkit::SockException &ex) {
    SPDLOG_INFO("{}:{} connect result:{}", _ip, _port, ex.what());

    if (ex.getErrCode() == toolkit::Err_success) {
        if (_timer)
            _timer = nullptr;

        if (_connected_callback)
            _connected_callback();
    } else {
        if (_auto_reconnect) {
            std::weak_ptr<TcpClient> self = std::dynamic_pointer_cast<TcpClient>(shared_from_this());
            _timer.reset(new toolkit::Timer(
                _reconnect_time,
                [self]() {
                    auto strong_self = self.lock();
                    SPDLOG_INFO("reconnecting to {}:{}", strong_self->_ip, strong_self->_port);
                    if (strong_self)
                        strong_self->Connect();
                    return false;
                },
                nullptr));
        }
    }
}

void TcpClient::Init(const std::string &ip, int port, float out_time) {
    _ip = ip;
    _port = port;
    _out_time = out_time;
}

void TcpClient::SetAutoReconnect(bool flag, float reconnect_time) {
    _auto_reconnect = flag;
    _reconnect_time = reconnect_time;
}

bool TcpClient::Connect() {
    this->startConnect(_ip, _port, _out_time * 1.0);
    return true;
}

bool TcpClient::IsAlive() {
    return alive();
}

void TcpClient::Disconnect() {
    this->_auto_reconnect = false;
    this->shutdown();
}

void TcpClient::SendData(const char *data, int len) {

    std::stringstream ss;
    for (int i = 0; i < len; i++) {
        ss << fmt::format("{:02X} ", (uint8_t)data[i]);
    }
    this->send(data, len);
}

void TcpClient::SetRcvDataCallback(std::function<void(const toolkit::Buffer::Ptr &)> f) {
    _data_callback = f;
}

void TcpClient::SetConnectedCallback(std::function<void()> f) {
    _connected_callback = f;
}
